package com.yh.gulimall.authserver.controller;

import com.alibaba.fastjson.TypeReference;
import com.yh.common.constant.AuthServiceConstant;
import com.yh.common.exception.BizCodeEnum;
import com.yh.common.utils.R;
import com.yh.common.vo.MemberRespVo;
import com.yh.gulimall.authserver.feign.MemberFeignService;
import com.yh.gulimall.authserver.feign.ThirdPartService;
import com.yh.gulimall.authserver.vo.UserLoginVo;
import com.yh.gulimall.authserver.vo.UserRegistVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotEmpty;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Controller
@Slf4j
public class LoginController {
//空方法用我们配置的视图映射
//    @GetMapping("/login.html")
//    public String login(){
//        return "login";
//    }
//    @GetMapping("/reg.html")
//    public String regPage(){
//        return "reg";
//    }

    @Autowired
    private ThirdPartService thirdPartService;

    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @Autowired
    private MemberFeignService memberFeignService;

    @ResponseBody
    @GetMapping(value = "/sms/sendCode")
    public R sendCode(@RequestParam("phone") String phone) {
        //1、接口防刷

        String redis_Code = stringRedisTemplate.opsForValue().get(AuthServiceConstant.SMS_CODE_CACHE_PREFIX + phone);
        if(!StringUtils.isEmpty(redis_Code)){
            long time = Long.parseLong(redis_Code.split("_")[1]);

            if(System.currentTimeMillis()-time<60000){
                //60秒内不能再发
                return R.error(BizCodeEnum.SMS_CODE_EXCEPTION.getCode(), BizCodeEnum.SMS_CODE_EXCEPTION.getMsg());
            }
        }

        //2、验证码再次校验。 redis 手机号做key 验证码做value  缓存前缀 sms:code:1554158 -> 666777
        //生成验证码
        Random random=new Random(System.currentTimeMillis());
        String code="";
        for(int i=0;i<6;i++){
            code=code+String.valueOf(random.nextInt(10));
        }
        //redis缓存10分钟，防止同一个手机号在60s内再次发送验证码
        String redisCode=code+"_"+System.currentTimeMillis();
        stringRedisTemplate.opsForValue().set(AuthServiceConstant.SMS_CODE_CACHE_PREFIX+phone,redisCode,10, TimeUnit.MINUTES);

        thirdPartService.sendCode(phone,code);
        return R.ok();
    }


    @PostMapping("/regist")
    public String regist(@Valid UserRegistVo vo, BindingResult result, RedirectAttributes attributes){
        //1、如果说字段校验出错
        if(result.hasErrors()){
            //使用map存储字段错误信息
            Map<String, String> errors = result.getFieldErrors().stream().collect(Collectors.toMap(error -> {
                return error.getField();
            }, error -> {
                return error.getDefaultMessage();
            }));
            attributes.addFlashAttribute("errors",errors);

//            Request method 'POST' not supported
//            用户注册-》regist[post]-->转发/regist.html(get)
//            return "forward:/reg.html";
            //TODO 重定向就是模拟我们的session的。所以我们重定向之后可以取到数据。  解决分布式session
            return "redirect:http://auth.gulimall.com/reg.html";
        }

        //2、校验验证码
        String code = vo.getCode();
        String redis_code = stringRedisTemplate.opsForValue().get(AuthServiceConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());
        if(!StringUtils.isEmpty(redis_code)){
            if(code.equals(redis_code.split("_")[0])){
               //验证码通过 删除验证码,令牌机制
                stringRedisTemplate.delete(AuthServiceConstant.SMS_CODE_CACHE_PREFIX + vo.getPhone());

                //3、检验通过，调用远程服务进行真正的注册
                R r = memberFeignService.regist(vo);
                if(r.getCode()==0){

                    return "redirect:http://auth.gulimall.com/login.html";
                }else {
                    //失败
                    Map<String, String> errors = new HashMap<>();
                    errors.put("msg", r.getData("msg",new TypeReference<String>(){}));
                    attributes.addFlashAttribute("errors",errors);
                    return "redirect:http://auth.gulimall.com/reg.html";
                }
            }else{
                Map<String, String> errors = new HashMap<>();
                errors.put("code", "验证码错误");
                attributes.addFlashAttribute("errors",errors);
                return "redirect:http://auth.gulimall.com/reg.html";
            }
        }else{
            Map<String, String> errors = new HashMap<>();
            errors.put("code", "验证码错误");
            attributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.gulimall.com/reg.html";
        }
    }

    @GetMapping("/login.html")
    public String loginPage(HttpSession session){
        Object attribute = session.getAttribute(AuthServiceConstant.LOGIN_USER);
        if(attribute==null){
            //没登录
            return "login";
        }
        return "redirect:http://gulimall.com";
    }

    @PostMapping("/login")
    public String login(UserLoginVo vo, RedirectAttributes redirectAttributes, HttpSession session){
        //远程登录
        R login = memberFeignService.login(vo);
        if(login.getCode()==0){
            MemberRespVo data = login.getData("data", new TypeReference<MemberRespVo>() {
            });
            session.setAttribute("loginUser",data);
            return "redirect:http://gulimall.com";
        }else{
            Map<String, String> errors = new HashMap<>();
            errors.put("msg", login.getData("msg",new TypeReference<String>(){}));
            redirectAttributes.addFlashAttribute("errors",errors);
            return "redirect:http://auth.gulimall.com/login.html";
        }
    }
}
